"""
试卷管理模块 - 信号处理
为试卷管理功能提供自动化处理和事件响应
"""
from django.db.models.signals import post_save, post_delete, pre_save
from django.dispatch import receiver
from django.db.models import Count, Avg, Sum
from django.utils import timezone
from django.core.cache import cache

from .models import (
    ExamPaperTemplate, ExamPaper, PaperSection, PaperQuestion,
    PaperAnalysis, PaperVersion
)


@receiver(post_save, sender=ExamPaperTemplate)
def template_created(sender, instance, created, **kwargs):
    """模板创建后的信号处理"""
    if created:
        # 缓存模板信息
        cache_key = f'template_{instance.id}'
        cache.set(cache_key, {
            'id': instance.id,
            'name': instance.name,
            'template_type': instance.template_type,
            'default_total_score': float(instance.default_total_score),
            'default_duration': instance.default_duration
        }, timeout=3600)  # 缓存1小时

        # 记录模板使用统计初始化
        cache.set(f'template_usage_{instance.id}', 0, timeout=86400)  # 缓存24小时


@receiver(post_save, sender=ExamPaperTemplate)
def template_updated(sender, instance, created, **kwargs):
    """模板更新后的信号处理"""
    if not created:
        # 更新缓存
        cache_key = f'template_{instance.id}'
        cache.delete(cache_key)

        # 如果模板设置为公开，更新公开模板缓存
        if instance.is_public:
            cache.delete('public_templates')


@receiver(post_save, sender=ExamPaper)
def paper_created(sender, instance, created, **kwargs):
    """试卷创建后的信号处理"""
    if created:
        # 缓存试卷基本信息
        cache_key = f'paper_{instance.id}'
        cache.set(cache_key, {
            'id': instance.id,
            'title': instance.title,
            'paper_type': instance.paper_type,
            'status': instance.status,
            'total_score': float(instance.total_score),
            'duration': instance.duration,
            'question_count': instance.question_count
        }, timeout=3600)

        # 增加模板使用次数
        if instance.template:
            instance.template.increment_usage()

        # 创建默认分析记录
        PaperAnalysis.objects.get_or_create(
            exam_paper=instance,
            defaults={
                'analysis_status': 'pending'
            }
        )


@receiver(post_save, sender=ExamPaper)
def paper_updated(sender, instance, created, **kwargs):
    """试卷更新后的信号处理"""
    if not created:
        # 检查状态变化
        if hasattr(instance, '_original_status'):
            old_status = instance._original_status
            new_status = instance.status

            if old_status != new_status:
                # 状态变化处理
                if new_status == 'published':
                    # 试卷发布时，清理相关缓存
                    cache.delete(f'paper_{instance.id}')
                    cache.delete('published_papers')

                elif new_status == 'reviewed':
                    # 试卷审核通过时，准备分析
                    analysis, created = PaperAnalysis.objects.get_or_create(
                        exam_paper=instance,
                        defaults={
                            'analysis_status': 'pending'
                        }
                    )
                    if not created and analysis.analysis_status == 'completed':
                        # 重新分析
                        analysis.analysis_status = 'pending'
                        analysis.save(update_fields=['analysis_status'])


@receiver(pre_save, sender=ExamPaper)
def paper_pre_save(sender, instance, **kwargs):
    """试卷保存前的信号处理"""
    if instance.pk:
        try:
            old_instance = sender.objects.get(pk=instance.pk)
            instance._original_status = old_instance.status
        except sender.DoesNotExist:
            instance._original_status = None
    else:
        instance._original_status = None


@receiver(post_save, sender=PaperQuestion)
def paper_question_created(sender, instance, created, **kwargs):
    """试卷题目创建后的信号处理"""
    if created:
        # 重新计算试卷总分
        paper = instance.exam_paper
        total_score = paper.paper_questions.aggregate(
            total=Sum('score')
        )['total'] or 0

        if total_score != paper.total_score:
            paper.total_score = total_score
            paper.save(update_fields=['total_score'])

        # 更新题目数量
        question_count = paper.paper_questions.count()
        if question_count != paper.question_count:
            paper.question_count = question_count
            paper.save(update_fields=['question_count'])

        # 重新计算平均难度
        calculate_paper_average_difficulty(paper)


@receiver(post_delete, sender=PaperQuestion)
def paper_question_deleted(sender, instance, **kwargs):
    """试卷题目删除后的信号处理"""
    paper = instance.exam_paper

    # 重新计算总分和题目数量
    total_score = paper.paper_questions.aggregate(
        total=Sum('score')
    )['total'] or 0

    question_count = paper.paper_questions.count()

    paper.total_score = total_score
    paper.question_count = question_count
    paper.save(update_fields=['total_score', 'question_count'])

    # 重新计算平均难度
    calculate_paper_average_difficulty(paper)


@receiver(post_save, sender=PaperSection)
def paper_section_created(sender, instance, created, **kwargs):
    """试卷部分创建后的信号处理"""
    if created:
        # 更新试卷部分数量缓存
        paper = instance.exam_paper
        cache_key = f'paper_sections_{paper.id}'
        cache.delete(cache_key)


@receiver(post_delete, sender=PaperSection)
def paper_section_deleted(sender, instance, **kwargs):
    """试卷部分删除后的信号处理"""
    paper = instance.exam_paper

    # 将该部分的题目移出部分
    instance.paper_questions.update(section=None)

    # 更新试卷部分数量缓存
    cache_key = f'paper_sections_{paper.id}'
    cache.delete(cache_key)


@receiver(post_save, sender=PaperAnalysis)
def analysis_created(sender, instance, created, **kwargs):
    """分析记录创建后的信号处理"""
    if created:
        # 缓存分析状态
        cache_key = f'paper_analysis_{instance.exam_paper.id}'
        cache.set(cache_key, {
            'id': instance.id,
            'status': instance.analysis_status,
            'quality_score': instance.quality_score,
            'created_at': instance.created_at
        }, timeout=3600)


@receiver(post_save, sender=PaperVersion)
def version_created(sender, instance, created, **kwargs):
    """试卷版本创建后的信号处理"""
    if created:
        # 清理试卷相关缓存
        paper = instance.exam_paper
        cache.delete(f'paper_{paper.id}')
        cache.delete(f'paper_versions_{paper.id}')


@receiver(post_save, sender=PaperVersion)
def version_updated(sender, instance, created, **kwargs):
    """试卷版本更新后的信号处理"""
    if not created and instance.is_current:
        # 如果设置为当前版本，清理试卷缓存
        paper = instance.exam_paper
        cache.delete(f'paper_{paper.id}')


def calculate_paper_average_difficulty(paper):
    """计算试卷平均难度"""
    try:
        # 获取所有题目的难度
        difficulties = []
        for paper_question in paper.paper_questions.select_related('question'):
            if paper_question.question.difficulty:
                difficulties.append(float(paper_question.question.difficulty))

        if difficulties:
            average_difficulty = sum(difficulties) / len(difficulties)
            paper.average_difficulty = round(average_difficulty, 2)
            paper.save(update_fields=['average_difficulty'])
    except Exception as e:
        # 计算失败时不影响正常流程
        pass


# 定时任务：清理过期缓存
def cleanup_paper_cache():
    """清理试卷相关的过期缓存"""
    from django.core.cache import cache
    from django.conf import settings

    # 清理试卷基础信息缓存
    papers = ExamPaper.objects.all()
    for paper in papers:
        cache_key = f'paper_{paper.id}'
        cache.delete(cache_key)

    # 清理模板缓存
    templates = ExamPaperTemplate.objects.all()
    for template in templates:
        cache_key = f'template_{template.id}'
        cache.delete(cache_key)

    # 清理分析缓存
    analyses = PaperAnalysis.objects.all()
    for analysis in analyses:
        cache_key = f'paper_analysis_{analysis.exam_paper.id}'
        cache.delete(cache_key)


# 定时任务：统计试卷使用情况
def update_paper_statistics():
    """更新试卷使用统计"""
    from datetime import timedelta
    from django.utils import timezone

    # 更新模板使用次数
    templates = ExamPaperTemplate.objects.all()
    for template in templates:
        usage_count = ExamPaper.objects.filter(template=template).count()
        if usage_count != template.usage_count:
            template.usage_count = usage_count
            template.save(update_fields=['usage_count'])

    # 更新试卷使用次数
    papers = ExamPaper.objects.all()
    for paper in papers:
        # 这里可以添加更多统计逻辑，比如最近使用时间等
        pass


# 信号连接函数
def connect_signals():
    """连接所有信号处理器"""
    # 这里可以添加额外的信号连接
    pass


# 自动连接信号
connect_signals()